/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package splab.ufcg.edu.br.trace.gui;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import splab.ufcg.edu.br.trace.entities.TraceLink;
import splab.ufcg.edu.br.trace.entities.TraceLinkList;
import splab.ufcg.edu.br.trace.enumeration.TraceLinkElementEnum;

/**
 * 
 * @author Arthur
 */
public class TraceTreeRepresenter extends javax.swing.JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8990772410338487746L;

	private boolean expand;

	private TraceLinkList lastResult;

	/**
	 * Creates new form TraceTreeRepresenter
	 */
	public TraceTreeRepresenter() {

		expand = false;

		initComponents();
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	private void initComponents() {

		this.initButtons();

		this.initTree();

		this.setOverallLayout();
	}

	private void setOverallLayout() {
		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
		this.setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						javax.swing.GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addGap(0, 325, Short.MAX_VALUE)
								.addComponent(expandCollapseButton))
				.addGroup(
						layout.createSequentialGroup().addContainerGap()
								.addComponent(treePanel).addContainerGap()));
		layout.setVerticalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						javax.swing.GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addContainerGap()
								.addComponent(treePanel,
										javax.swing.GroupLayout.DEFAULT_SIZE,
										253, Short.MAX_VALUE)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(expandCollapseButton)
								.addContainerGap()));
	}

	private void initTree() {
		traceTree.setBorder(javax.swing.BorderFactory.createTitledBorder(
				javax.swing.BorderFactory.createEtchedBorder(),
				"Retrieved Trace Links"));
		javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode(
				"Trace Links");
		traceTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
		traceTree
				.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
		treePanel.setViewportView(traceTree);
	}

	private void initButtons() {
		expandCollapseButton = new javax.swing.JButton();
		treePanel = new javax.swing.JScrollPane();
		traceTree = new javax.swing.JTree();

		setPreferredSize(new java.awt.Dimension(352, 294));
		setSize(new java.awt.Dimension(352, 294));

		expandCollapseButton.setIcon(new javax.swing.ImageIcon(getClass()
				.getResource("/icons/expand.gif")));
		expandCollapseButton.setSize(new java.awt.Dimension(27, 27));
		expandCollapseButton
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						expandCollapseButtonActionPerformed(evt);
					}
				});
	}

	private void expandCollapseButtonActionPerformed(
			java.awt.event.ActionEvent evt) {// GEN-FIRST:event_expandCollapseButtonActionPerformed

		expand = !expand;

		if (expand) {
			expandCollapseButton.setIcon(new javax.swing.ImageIcon(getClass()
					.getResource("/icons/collapse.gif")));

			for (int i = 0; i < traceTree.getRowCount(); i++) {
				traceTree.expandRow(i);
			}
		} else {
			expandCollapseButton.setIcon(new javax.swing.ImageIcon(getClass()
					.getResource("/icons/expand.gif")));

			for (int i = 0; i < traceTree.getRowCount(); i++) {
				traceTree.collapseRow(i);
			}
		}
	}

	public void filterButtonActionPerformed(java.awt.event.ActionEvent evt,
			TraceLinkElementEnum selectedElement, String selectedValue) {// GEN-FIRST:event_filterButtonActionPerformed

		DefaultTreeModel model = (DefaultTreeModel) traceTree.getModel();
		DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
		root.removeAllChildren();

		TraceLinkList filteredTraces = new TraceLinkList();
		List<TraceLink> relatedTraces = new ArrayList<TraceLink>();

		if (lastResult != null) {
			relatedTraces = this.getRelatedTraces(selectedElement, selectedValue);

		}

		filteredTraces.setTraceLinks(relatedTraces);

		Set<String> typesNodes = filteredTraces.getArtifactTypes();
		Set<String> semanticNodes = filteredTraces.getSemantics();
		Set<String> requirementNodes = filteredTraces.getRequirements();

		this.buildFilteredTree(root, filteredTraces, typesNodes, semanticNodes,
				requirementNodes);

		model.reload(root);
		expand = false;

		expandCollapseButton.setIcon(new javax.swing.ImageIcon(getClass()
				.getResource("/icons/expand.gif")));

	}

	private void buildFilteredTree(DefaultMutableTreeNode root,
			TraceLinkList filteredTraces, Set<String> typesNodes,
			Set<String> semanticNodes, Set<String> requirementNodes) {
		List<TraceLink> relatedTraces;
		for (String requirementNode : requirementNodes) {

			DefaultMutableTreeNode requirement = new DefaultMutableTreeNode(
					requirementNode);

			for (String semanticNode : semanticNodes) {
				DefaultMutableTreeNode semantic = new DefaultMutableTreeNode(
						semanticNode);

				for (String artifactTypeNode : typesNodes) {

					DefaultMutableTreeNode type = new DefaultMutableTreeNode(
							artifactTypeNode);

					relatedTraces = filteredTraces
							.filterByRequirementSemanticAndType(
									requirementNode, semanticNode,
									artifactTypeNode);

					for (TraceLink traceLink : relatedTraces) {

						DefaultMutableTreeNode artifact = new DefaultMutableTreeNode(
								traceLink.getArtifact());
						type.add(artifact);
					}

					semantic.add(type);

				}
				requirement.add(semantic);
			}
			root.add(requirement);
		}
	}

	private List<TraceLink> getRelatedTraces(TraceLinkElementEnum selectedElement,
			String selectedValue) {
		
		List<TraceLink> relatedTraces = new ArrayList<TraceLink>();
		
		for (TraceLink traceLink : lastResult.getTraceLinks()) {
			switch (selectedElement) {
			case REQUIREMENT:
				if (traceLink.getRequirement().equals(selectedValue)) {
					relatedTraces.add(traceLink);
				}
				break;

			case SEMANTIC:
				if (traceLink.getSemantic().equals(selectedValue)) {
					relatedTraces.add(traceLink);
				}
				break;

			case ARTIFACT_TYPE:
				if (traceLink.getArtifactType().equals(selectedValue)) {
					relatedTraces.add(traceLink);
				}
				break;

			case ARTIFACT:
				if (traceLink.getArtifact().equals(selectedValue)) {
					relatedTraces.add(traceLink);
				}
				break;
			default:
				break;
			}
		}
		return relatedTraces;
	}

	public boolean runButtonActionPerformed(java.awt.event.ActionEvent evt,
			TraceLinkList traceLinks) {// GEN-FIRST:event_runButtonActionPerformed

		DefaultTreeModel model = (DefaultTreeModel) traceTree.getModel();
		DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
		root.removeAllChildren();
		boolean result = false;
		

		try {

			

			Set<String> typesNodes = traceLinks.getArtifactTypes();
			Set<String> semanticNodes = traceLinks.getSemantics();
			Set<String> requirementNodes = traceLinks.getRequirements();

			for (String requirementNode : requirementNodes) {

				DefaultMutableTreeNode requirement = new DefaultMutableTreeNode(
						requirementNode);

				for (String semanticNode : semanticNodes) {
					DefaultMutableTreeNode semantic = new DefaultMutableTreeNode(
							semanticNode);

					for (String artifactTypeNode : typesNodes) {

						DefaultMutableTreeNode type = new DefaultMutableTreeNode(
								artifactTypeNode);

						List<TraceLink> relatedTraces = traceLinks
								.filterByRequirementSemanticAndType(
										requirementNode, semanticNode,
										artifactTypeNode);

						for (TraceLink traceLink : relatedTraces) {

							DefaultMutableTreeNode artifact = new DefaultMutableTreeNode(
									traceLink.getArtifact());
							type.add(artifact);
						}

						semantic.add(type);

					}
					requirement.add(semantic);
				}
				root.add(requirement);
			}

			result = true;

		} catch (Exception ex) {
			result = false;
		}

		model.reload(root);		

		expand = false;

		expandCollapseButton.setIcon(new javax.swing.ImageIcon(getClass()
				.getResource("/icons/expand.gif")));

		return result;

	}

	public void expandCollapseButton(java.awt.event.ActionEvent evt) {
		this.expandCollapseButtonActionPerformed(evt);
	}

	// Variables declaration - do not modify//GEN-BEGIN:variables
	public javax.swing.JButton expandCollapseButton;
	private javax.swing.JTree traceTree;
	private javax.swing.JScrollPane treePanel;

	// End of variables declaration//GEN-END:variables

	void setLastQueriedResult(TraceLinkList traceLinks) {
		this.lastResult = traceLinks;
	}

	TraceLinkList getLastQueriedResult() {
		return this.lastResult;
	}
}
